/*
 * File:   mbport.h
 * Author: Administrator
 *
 * Created on 2015年8月24日, 下午8:38
 * modify @ 20180804
 * --微调
 */

#ifndef __MBDEF_H
#define	__MBDEF_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "stdint.h"
#include "mbcrc.h"   
#include "dat_quene.h" 

	typedef unsigned char       mb_slave_id_type;
	typedef unsigned short      mb_reg_num_type;
	typedef unsigned short      mb_reg_addr_type;
	typedef unsigned short      mb_reg_data_type;

#ifndef MB_MUL_TASK_EN
#define MB_MUL_TASK_EN                          1
#endif

#ifndef MB_ASCII_EN
#define MB_ASCII_EN                             0
#endif

#define MB_BUFF_SIZE                            (256 )
#define MB_ERR_CNT_PV                           (  5 )
#define SMB_TIMEOUT_MS                          (6000)
#define MMB_TIMEOUT_MS                          (120 )

#define MB_EVENT_SEND_END                       (0x01)
#define MB_EVENT_RCV_END                        (0x02)

#define MB_FUN_READ_COILS_ENABLED               (  1 )  //fun: 01
#define MB_FUN_READ_DISCRETE_INPUTS_ENABLED     (  1 )  //fun: 02
#define MB_FUN_READ_REG_ENABLED                 (  1 )  //fun: 03    
#define MB_FUN_READ_INPUT_ENABLED               (  1 )  //fun: 04
#define MB_FUN_WRITE_COIL_ENABLED               (  1 )  //fun: 05
#define MB_FUN_WRITE_REG_ENABLED                (  1 )  //fun: 06
#define MB_FUN_WRITE_MULTIPLE_COILS_ENABLED     (  1 )  //fun: 15
#define MB_FUN_WRITE_MULTIPLE_REG_ENABLED       (  1 )  //fun: 16 
#define MB_FUN_W_R_MULTIPLE_REG_ENABLED         (  1 )  //fun: 0x17 

#define MB_REG_COILS_CB_ENABLE	    ( MB_FUN_READ_COILS_ENABLED + MB_FUN_WRITE_COIL_ENABLED + MB_FUN_WRITE_MULTIPLE_COILS_ENABLED  ) 
#define MB_REG_HOLDING_CB_ENABLE    ( MB_FUN_READ_REG_ENABLED + MB_FUN_WRITE_REG_ENABLED + MB_FUN_WRITE_MULTIPLE_REG_ENABLED + MB_FUN_W_R_MULTIPLE_REG_ENABLED )  
#define MB_REG_INPUT_CB_ENABLE	    ( MB_FUN_READ_INPUT_ENABLED   ) 
#define MB_REG_DISCRETE_CB_ENABLE   ( MB_FUN_READ_DISCRETE_INPUTS_ENABLED   )    

#define MB_COIL_ON                      0xFF00
#define MB_COIL_OFF                     0x0000

#define MB_ERR_CODE                     0x80
#define MB_FAULT_CODE1                  0x01
#define MB_FAULT_CODE2                  0x02
#define MB_FAULT_CODE3                  0x03
#define MB_FAULT_CODE4                  0x04

#define     MB_ERR_NONE        0        //!< no error. 
#define     MB_ERR_NOREG       1        //!< illegal register address. 
#define     MB_ERR_DATA        2 
#define     MB_ERR_CRC_LRC     3 
#define     MB_ERR_FUN_CODE    4
#define     MB_ERR_HAL         5
#define     MB_ETIMEDOUT       16       

#define    MB_SLAVE_ERR_CRC            11
#define    MB_SLAVE_ERR_HAL            12
#define    MB_SLAVE_ERR_ADDR           13
#define    MB_SLAVE_ERR_FUN_CODE       14
#define    MB_SLAVE_ERR_DATA           15
#define    MB_SLAVE_ERR_FRAME          16
#define    MB_SLAVE_ERR_UNKNOWN        127

#define     MB_NULL            (0)

	/* -----------------------  cmd Type definitions ---------------------------------*/
	typedef enum {
		FUN_CODE_NONE = 0,
		FUN_CODE_READ_COILS = 0x01,
		FUN_CODE_READ_DISCRETE = 0x02,
		FUN_CODE_READ_REG = 0x03,
		FUN_CODE_READ_INPUT = 0x04,
		FUN_CODE_WRITE_COIL = 0x05,
		FUN_CODE_WRITE_REG = 0x06,
		FUN_CODE_WRITE_MULTIPLE_COIL = 0x0F,
		FUN_CODE_WRITE_MULTIPLE_REG = 0x10,
		FUN_CODE_WRITE_MASK = 0x16,
		FUN_CODE_W_R_MULTIPLE_REG = 0x17,
		FUN_CODE_READ_SLAVE_ID = 0x2B,
		FUN_GUS_REG_WRITE = 0x80, //CRC 校验的开启/关闭由配置文件的 0x2C.6 位控制
		FUN_GUS_REG_READ = 0x81,
		FUN_GUS_PV_WRITE = 0x82,
		FUN_GUS_PV_READ = 0x83,
		FUN_GUS_LINE_WRITE = 0x84,
		FUN_GUS_AUTO = 0xEE, //无返回数据的自由指令
	} mb_cmd_type;

	/* -----------------------  dat Type definitions -------------------------*/
	typedef union {
		uint16_t Val;
		uint16_t uVal;
		int16_t iVal;
		struct {
			uint8_t LB;
			uint8_t HB;
		} byte;
	} mb_data_type;

	/* -----------------------  Receive State Type definitions ----------------*/
	typedef enum {
		MB_RX_IDLE, // Receiver is in idle state.
		MB_RX_RCV, // Frame is beeing received.
		MB_RX_RCVEND, // Port Receive complete ,3.5T timer
		MB_RX_WAIT, //Just for master
		MB_RX_TIMEOUT // Time out ,Send a command and no dat return after 500ms( --> system timer)
	} mb_rcv_st_type;

	/* -----------------------  Send State Type definitions -------------------*/
	typedef enum {
		MB_TX_IDLE, // Transmitter is in idle state.
		MB_TX_XMIT // Transmitter is in transfer state.
	} mb_snd_st_type;

	/* -----------------------  dat parity definitions -----------------------*/
	typedef enum {
		MB_PAR_NONE, /*!< No parity. */
		MB_PAR_ODD, /*!< Odd parity. */
		MB_PAR_EVEN, /*!< Even parity. */
		MB_PAR_NONE_1S,
	} mb_parity_type;

	/* -----------------------  RW Type definitions ---------------------------*/
	typedef enum {
		MB_REG_READ,
		MB_REG_WRITE,
	} mb_reg_mode_type;

	/* --------------------  Modbus mode Type definitions ---------------------*/
	typedef enum {
		MB_RTU_MASTER,
		MB_RTU_SLAVE,
		//ASCII_MASTER,
		//ASCII_SLAVE
	} mb_mode_type;

	/* ------------------  baudary Type definitions ---------------------------*/
	typedef enum {
		MB_BAUD_1200 = 0,
		MB_BAUD_2400 = 1,
		MB_BAUD_4800 = 2,
		MB_BAUD_9600 = 3,
		MB_BAUD_19200 = 4,
		MB_BAUD_38400 = 5,
		MB_BAUD_115200 = 6
	} mb_baud_type;

#define mb_baud_tab_create const uint32_t mb_baud_tab[] = {1200, 2400 ,4800, 9600, 19200, 38400, 115200}

	extern const uint32_t mb_baud_tab[];

	/* ------------------  Run State Type definitions -------------------------*/
	typedef union {
		uint32_t st;

		struct {
			uint8_t master_mode;
			uint8_t rtu_mode;
			uint8_t port_st;
			uint8_t connect;
		} bits;
	} mb_run_st_type;

	/* ------------------  Error State Type definitions -----------------------*/
	typedef union {
		uint32_t st;

		struct {
			uint8_t hal;
			uint8_t no_reg;
			uint8_t fun_code;
			uint8_t crc_lrc;
		} bits;
	} mb_err_st_type;

	/* ------------- master cmd Buffer struct Type definitions -----------------------*/
	typedef struct
	{
		void *dat; 		//data pointer
		mb_cmd_type cmd; 	//cmd  // IDLE indicate cansel the cmd
		uint8_t device_id; //slave id
		uint16_t dat_addr; //modbus data address
		uint16_t amount; 	//data amount
		void(*call_back)(uint8_t cmd_site, uint8_t err_st); //call back
	} mb_cmd_buff_type;

	/* ------------ slave extern Function Type definitions --------------------*/
	typedef struct {
		uint8_t(*reg_input_cb)(uint8_t * pucRegBuffer, uint16_t usAddress, uint16_t usNRegs);
		uint8_t(*reg_hold_cb)(uint8_t * pucRegBuffer, uint16_t usAddress, uint16_t usNRegs, mb_reg_mode_type eMode);
		uint8_t(*reg_discrete_cb)(uint8_t *pucRegBuffer, uint16_t usAddress, uint16_t usNCoils);
		uint8_t(*reg_coils_cb)(uint8_t * pucRegBuffer, uint16_t usAddress, uint16_t usNCoils, mb_reg_mode_type eMode);
	} smb_fun_type;

	/* ------------- master Function Type definitions -------------------------*/
	typedef struct {
		com_quene_type dcmd_quene;
		uint8_t err_cnt; //错误计数器 //发送新命令时自动清除一次
		uint8_t cmd_amount; //总缓冲池尺寸
		uint8_t cmd_exe_index; //当前处理命令索引
		uint8_t scmd_amount; //静态缓冲池尺寸
		uint8_t scmd_exe_index; //静态命令处理索引
		mb_cmd_buff_type* pcmdBuff; //指令指针 - 指向主机命令缓冲池
#if MB_MUL_TASK_EN > 0 
		void(*mutex_pend)(void);
		void(*mutex_post)(void);
#endif
	} mmb_fun_type;

	typedef struct
	{
		void(*rtu_timer_run)(void);
		void(*obj_init)(void);
		void(*mb_poll)(void);
		uint8_t(*os_stc_cmd_req)(uint8_t cmd_site, mb_cmd_buff_type* pcmd);
		uint8_t(*os_dyna_cmd_req)(mb_cmd_buff_type* pcmd);
		uint8_t(*os_stc_cmd_del)(uint8_t cmd_site);
		uint8_t(*stc_cmd_req)(uint8_t cmd_site, mb_cmd_buff_type* pcmd);
		uint8_t(*dyna_cmd_req)(mb_cmd_buff_type* pcmd);
		uint8_t(*stc_cmd_del)(uint8_t cmd_site);
		uint8_t(*cmd_ready_num)(void);
		uint8_t(*cmd_idle_num)(void);
		void(*cmd_clr)(void);
		void(*dgus_poll)(void);
		void(*dgusii_poll)(void);
		void(*vgus_poll)(void);
		void(*vgus_page_set)(uint16_t *page, void(*call_back)(uint8_t, uint8_t));
		void(*vgus_pv_read)(uint16_t *dat, uint16_t addr, uint16_t Len, void(*call_back)(uint8_t, uint8_t));
		void(*vgus_pv_write)(uint16_t *dat, uint16_t addr, uint16_t Len, void(*call_back)(uint8_t, uint8_t));
		//hal layer
		void(*tx1_rx0_enable)(uint8_t en_st);
		uint8_t(*rx_read)(void);
		void(*tx_write)(uint8_t dat);
	} mb_fun_interface_type;

	/* -------------- Modbus object Type definitions ---------------------------*/
	typedef struct {
		/*运行状态*/
		mb_run_st_type run_st; //运行状态
		mb_err_st_type err_st; //错误状态
		mb_rcv_st_type rcv_st; //接收状态       //硬件中断管理 //接收到字符设为RCV ，接收结束设为RCVEND //有操作系统时由外部设为TIMEOUT
		mb_snd_st_type snd_st; //发送状态       //报文发送结束由外部设为IDLE
		/*定时器管理*/
		uint8_t rtu_timer_cnt; //RTU结束判定计时器，用于软件定时
		uint8_t rtu_timer_sv;  //RTU结束判定设定值，用于软件定时
		uint8_t b_rtu_timer_on; //RTU定时器开启
		uint8_t rtu_rcv_end_keep_cnt; //RTU结束 //无OS时可用于做RCVEND延时处理的判定 //针对主机模式，从机无需延时，主机延时可以提供足够的间隔供其他不匹配从机复位状态
		uint8_t rtu_rcv_end_delay_set; //接收处理延时设定，带OS时设为0即可 //OS主机模式在发送函数前添加延时，如果确定只有一个从机时，也可以省略延时
		/*过程参数*/
		uint8_t slave_id; //从机id //仅在从模式设置；主模式由内部管理，禁止应用层修改。
		uint16_t timeout_cnt; //本机报文发送结束后开始计时//仅供主机 //应在串口ISR中清除
		uint16_t timeout_set;
		uint16_t rcv_cnt; //接收数据个数   //硬件中断及应用层管理 
		uint16_t snd_size; //待发送数据个数
		uint16_t snd_cnt; //发送过程计数
		/*事件定义*/
		uint16_t os_rtu_end_event; //RTU结束事件值 预设 //使用OS且用内部管理定时器时使用
		uint16_t os_timeout_event; //RTU超时事件值 预设 //使用OS且用内部管理定时器时使用
		/*状态监视*/
		uint16_t success_keep_cnt; //通信成功保持次数
		uint16_t fail_keep_cnt;   //通信失败保持次数
		uint16_t success_cnt;      //通信成功总次数
		uint16_t fail_cnt;        //通信失败总次数
		uint16_t active_keep_cnt; //活动状态计时 //包括 MB_TX_XMIT MB_RX_RCV 
		uint16_t active_keep_max; //活动状态计时最大值，用于调试监控
		uint16_t idle_time_cnt;   //空闲计时器，RX,TX均为IDLE时计时
		uint16_t sucess_none_time_cnt; //执行成功后计时，每次成功清除
		uint8_t adu_buff[MB_BUFF_SIZE]; //数据缓冲

		/*回调函数*/
		void(*adu_send)(void); //函数指针 - 发送adu_buff数据到端口，数量由snd_size指示
		void(*os_event_send)(uint16_t event); //使用OS是发送事件
		void(*rcv_end_handle_comp)(uint8_t err_st);

		/*功能接口*/
		smb_fun_type slave; //从机结构
		mmb_fun_type master; //主机结构
		mb_cmd_buff_type mcmd_now[2]; //当前正在处理的命令，搜索时加载，仅在接收处理时使用。

		const mb_fun_interface_type *api;
	} mb_obj_type;

	/*------------------------------------------------------*/
	typedef struct
	{
		uint8_t check_val_old;
		uint8_t release_time;
		uint8_t press_time;
		uint8_t opt_out;
	} mb_gus_keep_key_t;


	/* -------------- 状态机过程 ---------------------------*/
	/*
	从机：
	RX-IDLE&TX-IDLE -> RX-RCV&TX-IDLE -> RX-RCVEND&TX-IDLE -> RX-IDLE&TX-SEND -> RX-IDLE&TX-IDLE

	主机：
	RX-IDLE&TX-IDLE -> RX-RCV&TX-SEND -> RX-RCV&TX-IDLE -> RX-RCVEND&TX-IDLE -> RX-IDLE&TX-IDLE

	为尽量兼容其他设备，接收处理施加延时：

	对于含操作系统的应用，可以在数据发送函数添加任务延时即可。

	对于不含操作系统的应用--
	主机模式在接收结束后延时处理即可。
	从机接收到非本机地址直接处理，接收到本地地址延时处理。
	*/

#ifdef	__cplusplus
}
#endif

#endif	/* __MBDEF_H */

